#include "Torrent.h"
#include "Pieza.h"

Torrent::Torrent(const string &path, const string &idCliente, const unsigned long int puerto)
{
	this->path = path;
	this->idCliente = idCliente;
	this->puerto = puerto;

	this->tTracker = NULL;
	this->tPeersConectar = NULL;

	this->info = this->parser.parsear(path);

	if(this->info != NULL){
		this->tTracker = new ThreadTracker(this->info, this->idCliente, &this->colaPeersPorConectar, &this->conditionPeersPorConectar, this->puerto);
		this->tPeersConectar = new ThreadPeersConectar(this);

		this->tTracker->start();
		this->tPeersConectar->start();
		//TODO inicializar el manejador de archivos
		this->threadsArrancados = true;
	} else {
		this->threadsArrancados = false;
	}
}

Torrent::~Torrent()
{
	if(threadsArrancados){
		this->tTracker->join();
		this->tPeersConectar->join();
	}
	if (this->info != NULL) {
		delete info;
	}
}

Pieza* Torrent::asignarPiezaConMenosPeers(const string &idPeer) {

	InformacionPieza* infoPiezaAux = NULL;
	Pieza *piezaAsignada = NULL;
	bool encontradoPrimerCandidato = false;

	this->mutexPiezas.lock();
	list<InformacionPieza*>::iterator itPiezas = this->piezas.begin();

	for ( ; itPiezas != this->piezas.end(); itPiezas++) {
		InformacionPieza* piezaActual = *itPiezas;

		if (piezaActual->seEncuentraElCandidato(idPeer)) {

			if (encontradoPrimerCandidato) {
				/* Siempre se elige la pieza con menor cantidad de Peers */
				if (infoPiezaAux->getCantidadCandidatos() > piezaActual->getCantidadCandidatos()) {
					infoPiezaAux = piezaActual;
				}
			} else {
				infoPiezaAux = piezaActual;
				encontradoPrimerCandidato = true;
			}
		}
	}

	/* Si encontro una pieza crea una instancia de tipo Pieza para asignarsela al Peer.*/
	if (infoPiezaAux != NULL) {
		vector<string> hashes = this->info->getHashes();
		string hash = hashes[infoPiezaAux->getNroPieza()];

		piezaAsignada = new Pieza(hash, infoPiezaAux->getNroPieza(), this->info->getPiecesLength(), this->manejadorArchivos);
	}

	this->mutexPiezas.unlock();

	return piezaAsignada;
}

string Torrent::getPath() {
	return this->path;
}

TorrentInfo* Torrent::getTorrentInfo() {
	return this->info;
}

unsigned long long int Torrent::getBajado() {

}

void Torrent::pausar(bool pausar) {

}

void Torrent::reanudar() {

}

bool Torrent::getPausado() {

}

void Torrent::remover() {

}

list<unsigned long int> Torrent::getPiezasBajadas() {
	return this->getPiezasBajadas();
}

string Torrent::getId() {

}
